package com.cloudinnov.task;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.cloudinnov.dao.SectionDao;
import com.cloudinnov.model.EquipmentPoints;
import com.cloudinnov.model.Equipments;
import com.cloudinnov.model.Section;
import com.cloudinnov.utils.support.spring.SpringUtils;
import com.cloudinnov.websocket.ElectricMonitorWebsocket;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

public class ElectricMonitor {

	private static final Logger logger = LoggerFactory.getLogger(SchduleScanJob.class);
	private static final String POINT_NAME = "point:";
	private static final String VALUE_NAME = ":value";
	private static final String REALTIME_SPLITTER_LEVEL1 = ",";
	private static final String REALTIME_SPLITTER_LEVEL2 = ";";
	private static final String ElectricHead="electric:";
	private static final String ElectricFoot=":value";
	private static final String ExpressDot=",";
	private static final int REALTIME_TIME_LEVEL1 = 0;
	private static final int REALTIME_TIME_OUT_SECOND = 60;
	private static final int REALTIME_TIME_OUT_MILL = 1000;
	private static final int EXPIRETIME = 1000;
	private static final int NormalLine=0;
	private static final int BreakLine=1;
	private static final String BreakLineZh="断路";
	private static final int ShortLine=2;
	private static final String ShortLineZh="短路";
	private static final String RatedCurrent="32";
	private static final double overLoadRate=1.5;
			
	
	private ScheduledThreadPoolExecutor exec;
	SectionDao sectionDao = SpringUtils.getBean("sectionDao");
	JedisPool jedisPool = SpringUtils.getBean("jedisPool");
	private List<String> faultEquipCodeList = null;
	private List<String> repeatFaultParentEquipCodeList = null;
	Jedis redis = null;
	
	
	public void execute() {

 		exec = new ScheduledThreadPoolExecutor(1);
		exec.scheduleAtFixedRate(new SchedultTask(), 2000, 3000, TimeUnit.MILLISECONDS);

	}
	
	/**
	 * 定时任务线程runnable
	 * @author Administrator
	 *
	 */
	class SchedultTask implements Runnable {

		@Override
		public void run() {
			 breakLineDetect();
		}

	}

	/**
	 * 断路检测
	 */
	public void breakLineDetect() {

		List<Section> sectionInfo = sectionDao.selectSectionEquipmentNodeClassPoint();
		for (int i = 0; i < sectionInfo.size(); i++) {
			List<Equipments> sectionEquipments = sectionInfo.get(i).getSectionEquipments();// 当前隧道下的设备集合
			List<String> normalDeviceBySection = isNormalDeviceBySection(sectionEquipments);
		}

	}

	/**
	 * 对一个路段的设备进行检测
	 * @param sectionEquipments
	 * @return
	 */
	public List<String> isNormalDeviceBySection(List<Equipments> sectionEquipments) {
		faultEquipCodeList = new ArrayList<>();
		repeatFaultParentEquipCodeList = new ArrayList<>();
		
		try {
			redis = jedisPool.getResource();
			for (int i = 0; i < sectionEquipments.size(); i++) {
				if (repeatFaultParentEquipCodeList.contains(sectionEquipments.get(i).getParentCode())) {// 对于不包含父层节点的
					repeatFaultParentEquipCodeList.add(sectionEquipments.get(i).getCode());
				} else {
					List<EquipmentPoints> points = sectionEquipments.get(i).getPoints();
					boolean breakFlag = isBreak(points, sectionEquipments.size(),redis,sectionEquipments.get(i).getCode(),sectionEquipments.get(i).getName(),sectionEquipments.get(i).getRatedCurrent(),sectionEquipments.get(i).getCategoryCode(),sectionEquipments.get(i).getLocation());
					if (breakFlag) {
						faultEquipCodeList.add(sectionEquipments.get(i).getCode());
						repeatFaultParentEquipCodeList.add(sectionEquipments.get(i).getCode());
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			jedisPool.returnResource(redis);
		}
		return faultEquipCodeList;
	}

	public void saveFaultToRedis(Jedis redis,String code,String equipName,String faultType,String categoryCode, String location) throws IOException {
		if(redis.get(ElectricHead+code+ElectricFoot)==null) {
			redis.set(ElectricHead+code+ElectricFoot, faultType);
			//设置redis的失效时间
//			redis.expire(ElectricHead+code+ElectricFoot, EXPIRETIME);
			HashMap<String,String> alarmMsgMap = new HashMap<>();
			alarmMsgMap.put("msgType", "electricAlarm");
			alarmMsgMap.put("equipCode", code);
			alarmMsgMap.put("faultType", redis.get(ElectricHead+code+ElectricFoot));
			alarmMsgMap.put("equipName", equipName);
			alarmMsgMap.put("solutionAdvice", "请检查该回路空开是否断开");
		    alarmMsgMap.put("categoryCode", categoryCode);
		    alarmMsgMap.put("location", location);
			sendMsg(alarmMsgMap);
			logger.debug(alarmMsgMap.toString());
			System.err.println(alarmMsgMap);
		}
	}
	
	/**
	 * 调用 传送设备的所有点位  设备的数量  
	 * @param points
	 * @param equipmentSize
	 * @return 返回该设备是否断路的布尔值
	 * @throws IOException 
	 */
	public boolean isBreak(List<EquipmentPoints> points, int equipmentSize,Jedis redis,String equipCode,String equipName,Integer dL ,String categoryCode, String location) throws IOException {
		 
			int time = (int) (1.5 * equipmentSize);
			Map<String, String> map = new java.util.HashMap<>();
			String UACode=null;
			String UBCode=null; 
			String UCCode =null;
			String IACode=null;
			String IBCode=null;
			String ICCode=null;
			for (int i = 0; i < points.size(); i++) {
				String indexType = points.get(i).getIndexType();
				if (indexType.equals("UA")) {
					UACode = points.get(i).getCode();
				} else if (indexType.equals("UB")) {
					UBCode = points.get(i).getCode();
				} else if (indexType.equals("UC")) {
					UCCode = points.get(i).getCode();
				}else if(indexType.equals("ELECTRICA")) {
					IACode=points.get(i).getCode();
				}else if(indexType.equals("ELECTRICB")) {
					IBCode=points.get(i).getCode();
				}else if(indexType.equals("ELECTRICC")) {
					ICCode=points.get(i).getCode();
				}
			}
			String UAKey=POINT_NAME+UACode+VALUE_NAME;
			String UBKey=POINT_NAME+UBCode+VALUE_NAME;
			String UCKey=POINT_NAME+UCCode+VALUE_NAME;
			String IAKey=POINT_NAME+IACode+VALUE_NAME;
			String IBKey=POINT_NAME+IBCode+VALUE_NAME;
			String ICKey=POINT_NAME+ICCode+VALUE_NAME;
			
			if(isTimeOut(UAKey, time,redis,dL,IAKey)==BreakLine||isTimeOut(UBKey, time,redis,dL,IBKey)==BreakLine||isTimeOut(UCKey, time,redis,dL,ICKey)==BreakLine) {
				if(isTimeOut(UAKey, time,redis,dL,IAKey)==ShortLine||isTimeOut(UBKey, time,redis,dL,IBKey)==ShortLine||isTimeOut(UCKey, time,redis,dL,ICKey)==ShortLine) {
					saveFaultToRedis(redis,equipCode,equipName,ShortLineZh,categoryCode,location);//在断路的基础上判断是否是短路
				}else {
					saveFaultToRedis(redis,equipCode,equipName,ShortLineZh,categoryCode,location);//全部都没有超电流点判断为断路
				}
				return true;
			}else {
				 if(redis.get(ElectricHead+equipCode+ElectricFoot)!=null) {
					 redis.del(ElectricHead+equipCode+ElectricFoot);//电路正常
				 }
				 return false;
			}
	}

	/**
	 * 判断点位值是否超时断路
	 * @param key
	 * @param time
	 * @return
	 */
	public Integer isTimeOut(String key,int time,Jedis redis,Integer dL,String IKey) {
		String value = redis.lindex(key, 0);
		String iValue=redis.lindex(IKey, 0);
		if (value != null ) {
			value = value.replace(" ", "");
			iValue = iValue.replace(" ", "");
			String[] valueArray = value.split(REALTIME_SPLITTER_LEVEL1);
			String[] iValueArray=value.split(REALTIME_SPLITTER_LEVEL1);
			/**
			 * 判断实时redis中的第一条数据时间和当前时间相差是否大于60s
			 */
			long timeout = 0L;
			if (valueArray[0].length() > 11) {
				timeout = (System.currentTimeMillis() - Long.parseLong(valueArray[0])) / REALTIME_TIME_OUT_MILL;
			} else {
				timeout = ((System.currentTimeMillis() / 1000) - Long.parseLong(valueArray[0]));
			}
			if (timeout < time) {//在时间范围内
				if(Double.parseDouble(valueArray[1])==0) {//对电压进行判断   如果电压为0  判断为断路
					double dy = Double.parseDouble(iValueArray[1]);//实际电流值
					 
					double scale=dy/dL;
					if(scale>overLoadRate) {
						return ShortLine;
					}else {
						return BreakLine;
					}
				}else {
					return NormalLine;
				}
				 
			}else {//超时时做判断
				double dy = Double.parseDouble(iValueArray[1]);//实际电流值
				int ratedCurrent = Integer.parseInt(RatedCurrent);//额定电流值
				double scale=dy/ratedCurrent;
				if(scale>overLoadRate) {
					return ShortLine;
				}else {
					return BreakLine;
				}

			}
		}else {
			return BreakLine;
		}
	}
	
	public void sendMsg(Map<String, String> data) throws IOException {
		Iterator<Map.Entry<String, ElectricMonitorWebsocket>> equipmentStateWebsocket = ElectricMonitorWebsocket.webSocketMap.entrySet().iterator();
		while (equipmentStateWebsocket.hasNext()) {
			Map.Entry<String, ElectricMonitorWebsocket> electricWebsocketEntry = equipmentStateWebsocket.next();
				electricWebsocketEntry.getValue().sendMessage(JSON.toJSONString(data));
		}
	}
 
}
